package com.etonedu.meals.service;

import android.app.Service;
import android.content.Intent;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;
import android.widget.Toast;

import androidx.annotation.Nullable;

import com.blankj.utilcode.util.LogUtils;
import com.etonedu.meals.bean.AttendanceDate;
import com.etonedu.meals.bean.StudentBean;
import com.etonedu.meals.bean.StudentBean_;
import com.etonedu.meals.common.SPConst;
import com.etonedu.meals.dao.DaoUtils;
import com.etonedu.meals.http.LogReportUtils;
import com.etonedu.meals.utils.SharedPreferencesUtil;
import com.etonedu.meals.utils.Utils;

import org.greenrobot.eventbus.EventBus;
import org.xutils.x;

import java.io.IOException;
import java.security.InvalidParameterException;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

import comAssistant.MyFunc;
import comAssistant.SerialHelper;
import comAssistant.bean.ComBean;
import io.objectbox.Box;
import io.objectbox.BoxStore;

public class CardService extends Service {

    private SerialControl serialControl;
    private SerialControl serialControl1;
    private DispQueueThread dispQueue;//刷新显示线程

    public static final int SERIAL = 100010;

//    private AttendanceDateDao dao;

    private int count = 0;
    private Handler handler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == SERIAL) {
                String data = msg.obj.toString();
                if (TextUtils.isEmpty(data)) return;

                String model = Build.MODEL;
                String card = "";
                LogUtils.e("model = " + model);
                if ("rk3288".equals(model) || "B215ANL".equals(model) || "ZC-83E".equals(model) || "rk3288_box".equals(model)) {
                    card = data.replaceAll("\r|\n", "");
                } else {
                    card = Utils.getCardNum(data);
                }
                LogUtils.e("card = " + card);
                if (!Utils.isEmpty(card)) {
                    SharedPreferencesUtil spu = SharedPreferencesUtil.getInstance(x.app());
                    boolean atten = spu.getBoolean(SPConst.ATTEN_ACTIVITY,false);
                    boolean atten1 = spu.getBoolean(SPConst.ATTEN_ACTIVITY_1,false);

                    if (atten) {
                        count++;
                    } else {
                        count = 0;
                    }
                    String time = Utils.timestamp2String1(System.currentTimeMillis(), "yyyyMMddHHmmss");
//                    Notify notify = new Notify(NotifyInterface.CARD, card);
//                    notify.setTime(time);
//                    notify.setCount(count+"");
//                    EventBus.getDefault().postSticky(notify);


                    String mode = spu.getString(SPConst.ATTEN_MODE);
                    String token = spu.getString(SPConst.TOKEN);
                    if (atten || atten1) {
                        save2DB(card,time,mode);
                    }

                    String time1 = Utils.timestamp2String1(System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss");
//                    LogReportUtils.logCardNum("",count + "",card,time1,"","");
                }
            }
        }
    };

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        return START_STICKY;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        initSerial();
    }

    // 初始化刷卡
    private void initSerial() {
//        comAssistantUtils = ComAssistantUtils.getInstance(this);
//        comAssistantUtils.setHandler(handler);
//
//        comAssistantUtils.openComPort();
        int version = Utils.getAndroidSDKVersion();
        String model = Build.MODEL;
        String cpuInfo = Build.CPU_ABI;
        LogUtils.e("model = " + model);

        if (version == Build.VERSION_CODES.LOLLIPOP_MR1 || "rk3288_box".equals(model)) {
            if ("ZK-R329".equals(model)) {
                serialControl = new SerialControl("/dev/ttyS4", "19200");
                serialControl1 = new SerialControl("/dev/ttyS1", "19200");
            } else {
                serialControl = new SerialControl("/dev/ttyS3", "9600");
            }
        } else {
            if ("M3".equals(model) || "rk3288".equals(model)) {
                int ver = Utils.getAndroidSDKVersion();
//                if (ver == Build.VERSION_CODES.N_MR1) { // 聚贤
//                    serialControl = new SerialControl("/dev/ttyS0", "9600");
//                } else {
                    serialControl = new SerialControl("/dev/ttyS3", "9600");
//                }

            } else if ("SoftwinerEvb".equals(model)) {
                serialControl = new SerialControl("/dev/ttyS7", "9600");
            } else if ("rk3188".equals(model)) {
                serialControl = new SerialControl("/dev/ttyS1", "4800");
            } else if ("B215ANL".equals(model)) {
                serialControl = new SerialControl("/dev/ttyS3", "9600");
                LogUtils.e("初始化串口");
            } else if ("Octopus A83t".equals(model)) {
                serialControl = new SerialControl("/dev/ttyS4", "9600");
            } else if ("ZC-83E".equals(model)) {
                serialControl = new SerialControl("/dev/ttyS3", "9600");
            } else if ("rk3288_box".equals(model)) {
                serialControl = new SerialControl("/dev/ttyS3", "9600");
            } else {
                serialControl = new SerialControl("/dev/ttyS3", "9600");
            }
        }

//        serialControl = new SerialControl("/dev/ttyS4", "9600");
        dispQueue = new DispQueueThread();
        dispQueue.start();

        openComPort();

    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        closeComPort();
    }

    //----------------------------------------------------串口控制类
    private class SerialControl extends SerialHelper {

        //		public SerialControl(String sPort, String sBaudRate){
//			super(sPort, sBaudRate);
//		}
        public SerialControl() {
        }

        public SerialControl(String sPort, String sBaudRate) {
            super(sPort, sBaudRate);
        }

        @Override
        protected void onDataReceived(final ComBean comRecData) {
            //数据接收量大或接收时弹出软键盘，界面会卡顿,可能和6410的显示性能有关
            //直接刷新显示，接收数据量大时，卡顿明显，但接收与显示同步。
            //用线程定时刷新显示可以获得较流畅的显示效果，但是接收数据速度快于显示速度时，显示会滞后。
            //最终效果差不多-_-，线程定时刷新稍好一些。
            if (comRecData != null) {
                String data = dispRecData(comRecData);
                LogUtils.e("data = " + data);
            }
            dispQueue.addQueue(comRecData);//线程定时刷新显示(推荐)
			/*
			runOnUiThread(new Runnable()//直接刷新显示
			{
				public void run()
				{
					DispRecData(ComRecData);
				}
			});*/
        }
    }

    //----------------------------------------------------刷新显示线程
    private class DispQueueThread extends Thread {
        private Queue<ComBean> QueueList = new LinkedList<ComBean>();

        @Override
        public void run() {
            super.run();
            while (!isInterrupted()) {
                try {
                    final ComBean comData;
                    while ((comData = QueueList.poll()) != null) {
                        String data = dispRecData(comData);
                        LogUtils.e("data = " + data);
                        if (TextUtils.isEmpty(data)) return;
                        LogUtils.e("data = " + data);
                        handler.obtainMessage(CardService.SERIAL, data).sendToTarget();
                        String model = Build.MODEL;
                        LogUtils.e("model = " + model);
                        if ("rk3188".equals(model)) {
                            try {
                                Thread.sleep(100);
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        } else {
                            try {
                                Thread.sleep(50);//显示性能高的话，可以把此数值调小。
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                        break;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        public synchronized void addQueue(ComBean ComData) {
            QueueList.add(ComData);
        }
    }

    //----------------------------------------------------显示接收数据
    private String dispRecData(ComBean comRecData) {
        StringBuilder sMsg = new StringBuilder();

        String model = Build.MODEL;
        LogUtils.e(model);
        if ("rk3288".equals(model) || "B215ANL".equals(model) || "ZC-83E".equals(model) || "rk3288_box".equals(model)) {
            sMsg.append(new String(comRecData.bRec));
            String msg = new String(comRecData.bRec);
            LogUtils.e("bRec = " + msg);

        } else {
            sMsg.append(MyFunc.ByteArrToHex(comRecData.bRec));
            String msg = MyFunc.ByteArrToHex(comRecData.bRec);
            LogUtils.e("bRec = " + msg);
        }
        LogUtils.e("sMsg = " + sMsg.toString());
        return sMsg.toString();
    }

    //----------------------------------------------------关闭串口
    public void closeComPort() {
        if (serialControl != null) {
            serialControl.stopSend();
            serialControl.close();
        }
        if (serialControl1 != null) {
            serialControl1.stopSend();
            serialControl1.close();
        }
    }

    //----------------------------------------------------打开串口
    public void openComPort() {
        String model = Build.MODEL;
        try {
            if (serialControl != null) {
                serialControl.open();
                LogUtils.e("打开串口");
            }
            if (serialControl1 != null) {
                serialControl1.open();
            }
        } catch (SecurityException e) {
            showMessage("打开串口失败:没有串口读/写权限!");
            String time1 = Utils.timestamp2String1(System.currentTimeMillis(),"yyyy-MM-dd HH:mm:ss");
            String pagek = "com.etonedu.general.edu.service";
            LogReportUtils.log("打开串口失败:没有串口读/写权限!型号:"+model,pagek,Utils.getLineInfo(),time1);
            e.printStackTrace();
        } catch (IOException e) {
            showMessage("打开串口失败:未知错误!");
            String time1 = Utils.timestamp2String1(System.currentTimeMillis(),"yyyy-MM-dd HH:mm:ss");
            String pagek = "com.etonedu.general.edu.service";
            LogReportUtils.log("打开串口失败:未知错误!型号:"+model,pagek,Utils.getLineInfo(),time1);
        } catch (InvalidParameterException e) {
            showMessage("打开串口失败:参数错误!");
            String time1 = Utils.timestamp2String1(System.currentTimeMillis(),"yyyy-MM-dd HH:mm:ss");
            String pagek = "com.etonedu.general.edu.service";
            LogReportUtils.log("打开串口失败:参数错误!型号:"+model,pagek,Utils.getLineInfo(),time1);
        }
    }

    //------------------------------------------显示消息
    private void showMessage(String sMsg) {
        Toast.makeText(x.app(), sMsg, Toast.LENGTH_SHORT).show();
    }

    private void sendPortData(SerialHelper ComPort, String sOut) {
        if (ComPort != null && ComPort.isOpen()) {
            ComPort.sendHex(sOut);
        }
    }

    public void sendPortData(String sOut) {
        sendPortData(serialControl, sOut);
    }

    private void save2DB(String cardNo,String time,String mode) {
        try {
            SharedPreferencesUtil spu = SharedPreferencesUtil.getInstance(x.app());
            int isAccurate = spu.getInt(SPConst.IS_ACCURATE);
            String className = spu.getString(SPConst.CLASS_NAME);

            int noClass = 0;
            if (isAccurate == 1) { // 精准考勤
                Box<StudentBean> box = DaoUtils.getBoxStudent();
                List<StudentBean> classList = box.query().equal(StudentBean_.className,className).equal(StudentBean_.cardNo,cardNo).
                        equal(StudentBean_.roleType,1).or().
                        equal(StudentBean_.roleType,4).build().find();

                if (Utils.listIsNullOrEmpty(classList)) {
                    Box<StudentBean> box1 = DaoUtils.getBoxStudent();
                    List<StudentBean> noClassList = box1.query().equal(StudentBean_.cardNo,cardNo).
                            equal(StudentBean_.roleType,1).or().
                            equal(StudentBean_.roleType,4).build().find();

                    if (!Utils.listIsNullOrEmpty(noClassList)) {// 进错教室
                        noClass = 1;
                    }
                }
            }

            String dev = Utils.getDevCode();
            AttendanceDate date = new AttendanceDate();
            date.setAttenType(1);
            date.setCardNo(cardNo);
            date.setIsUpdatePic("0");
            date.setAttenTime(time);
            date.setDeviceCode(dev);
            date.setMode(mode);
            date.setNoClass(noClass);

            BoxStore boxStore = DaoUtils.getBoxStore();
            Box<AttendanceDate> box = boxStore.boxFor(AttendanceDate.class);
            box.put(date);

        } catch (Exception e) {
            e.printStackTrace();

        }
    }
}
